package com.onec.service.customer.service.impl;

import cn.hutool.core.date.DateUtil;
import com.onec.service.api.dto.request.gateway.BizContent;
import com.onec.service.api.enums.ProductEnum;
import com.onec.service.api.enums.StatusEnum;
import com.onec.service.api.enums.error.MerchantErrorEnum;
import com.onec.service.api.exception.CustomerException;
import com.onec.service.customer.dao.merchant.MerchantBusinessRepository;
import com.onec.service.customer.dao.merchant.MerchantInfoRepository;
import com.onec.service.customer.entity.agent.AgentInfo;
import com.onec.service.customer.entity.merchant.MerchantBusiness;
import com.onec.service.customer.entity.merchant.MerchantInfo;
import com.onec.service.customer.service.MerchantInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/**
 * 机构信息查询服务类；
 *
 * @author onec
 */
@Slf4j
@Service
public class MerchantInfoServiceImpl implements MerchantInfoService {


    @Autowired
    MerchantInfoRepository merchantInfoRepository;
    @Autowired
    MerchantBusinessRepository merchantBusinessRepository;

    /**
     * 获取商户信息：
     *
     * @param merchantNo
     * @return
     */
    @Override
    public MerchantInfo getMerchantInfo(String merchantNo) {
        MerchantInfo merchantInfo = merchantInfoRepository.findMerchantInfoByCode(merchantNo);
        if (Optional.ofNullable(merchantInfo).isEmpty()) {
            throw new CustomerException(MerchantErrorEnum.MERCHANT_INFO_EMPTY, "");
        }
        return merchantInfo;
    }

    /**
     * 获取可用商户信息：
     *
     * @param merchantNo
     * @return
     */
    @Override
    public MerchantInfo getAvailableMerchant(String merchantNo) {
        MerchantInfo merchantInfo = this.getMerchantInfo(merchantNo);
        if (StatusEnum.isSuccess(merchantInfo.getStatus())) {
            return merchantInfo;
        }
        // 冻结：
        if (StatusEnum.isFreeze(merchantInfo.getStatus())) {
            throw new CustomerException(MerchantErrorEnum.MERCHANT_INFO_STATUS_ERROR, merchantInfo.getStatus().name());
        }    // 冻结：
        if (StatusEnum.isInit(merchantInfo.getStatus())) {
            throw new CustomerException(MerchantErrorEnum.MERCHANT_INFO_STATUS_ERROR, merchantInfo.getStatus().name());
        }

        return merchantInfo;
    }

    /**
     * 商户业务信息：
     *
     * @param businessNo
     * @return
     */
    @Override
    public MerchantBusiness getMerchantBusiness(long merchantId, String businessNo) {

        MerchantBusiness merchantBusiness = merchantBusinessRepository
                .findByBusinessNoAndMerchantId(businessNo, merchantId);
        if (Optional.ofNullable(merchantBusiness).isEmpty()) {
            // 没有开通业务：
            throw new CustomerException(MerchantErrorEnum.PRODUCT_MERCHANT_NO_OPEN, businessNo);
        }

        return merchantBusiness;
    }

    @Override
    public MerchantInfo createMerchant(BizContent bizContent, AgentInfo agentInfo) {

        // 检查外部商户号是否已经存在：
        if (this.updateMerchantOutCode(bizContent.getOutCode())) {
            throw new CustomerException(MerchantErrorEnum.EXIST_OUT_CODE, "");
        }
        MerchantInfo merchantInfo = new MerchantInfo();
        merchantInfo.setVersion(1);
        merchantInfo.setStatus(StatusEnum.SUCCESS);
        merchantInfo.setAgentId(agentInfo.getId());
        // 敏感信息
        merchantInfo.setCardNo(bizContent.getCardNo());
        merchantInfo.setPhone(bizContent.getPhone());
        merchantInfo.setIdCard(bizContent.getIdCard());
        merchantInfo.setName(bizContent.getName());

        // 地区编码信息：
        merchantInfo.setProvince(bizContent.getProvince());
        merchantInfo.setCity(bizContent.getCity());
        merchantInfo.setCountry(bizContent.getCountry());
        merchantInfo.setAddress(bizContent.getAddress());
        merchantInfo.setOutCode(bizContent.getOutCode());

        // 商户信息配置：
        merchantInfo.setContacts(agentInfo.getContacts());
        merchantInfo.setRemarks("系统商户注册：" + agentInfo.getAgentCode());
        merchantInfo.setCreateTime(DateUtil.date());
        merchantInfo.setUpdateTime(DateUtil.date());
        merchantInfo.setCreator("系统入件");
        merchantInfo.setProduct(ProductEnum.DEFAULT);

        merchantInfo = merchantInfoRepository.save(merchantInfo);
        Long merchantNo = 100000000L + merchantInfo.getId();
        log.info("商户注册：机构编号：{}，生成的商户编号：{}", agentInfo.getAgentCode(), merchantNo);
        merchantInfo.setCode(agentInfo.getAgentCode().substring(0, 1) + merchantNo);
        merchantInfo = merchantInfoRepository.save(merchantInfo);
        return merchantInfo;
    }

    /**
     * 查询下游商户编号的时候增加行级锁
     * 避免下游多线程报备商户发生异常的问题：
     *
     * @param merchantInfo
     * @return
     * @deprecated 该方法仅供测试暂不使用：使用：updateMerchantOutCode() 方法替代：
     */
    @Deprecated
    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public MerchantInfo lockCreateMerchant(MerchantInfo merchantInfo) {
        if (Optional.ofNullable(merchantInfoRepository
                .findMerchantInfoByOutCode(merchantInfo.getOutCode())).isPresent()) {
            throw new CustomerException(MerchantErrorEnum.EXIST_OUT_CODE, "");
        }
        merchantInfo = merchantInfoRepository.save(merchantInfo);
        return merchantInfo;
    }

    /**
     * 通过外部商户号修改数据，修改成功证明该数据存在：
     *
     * @param outCode
     * @return
     */
    @Override
    public boolean updateMerchantOutCode(String outCode) {
        Integer result = merchantInfoRepository.updateMerchantInfoByOutCode(DateUtil.date(), outCode);
        return result > 0;
    }
}
